package org.xx.armory.swing.builders;

import org.xx.armory.objectparser.LineInfo;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

import static org.apache.commons.lang3.StringUtils.trimToEmpty;
import static org.xx.armory.commons.Validators.greaterThan;
import static org.xx.armory.commons.Validators.greaterThanOrEqual;

/**
 * 文本框的界面模型。
 */
public class TextModel
        extends AbstractComponentModel
        implements ComponentModel, ValidationModel {
    private final int size;
    private final int rowSize;
    private final boolean required;
    private final int maxLength;
    private final String minValue;
    private final String maxValue;
    private final String pattern;
    private final String optionsName;
    private final String prefix;
    private final String suffix;
    private final List<OptionModel> options;
    private TextModelType type;

    /**
     * 构造文本输入框的界面模型。
     *
     * @param lineInfo
     *         源文件中的位置信息。
     * @param name
     *         输入框的名字。
     * @param type
     *         输入框的类型。
     * @param size
     *         输入框的宽度(单位是列)。
     * @param rowSize
     *         输入框的高度(单位是行)
     * @param required
     *         是否必填。
     * @param maxLength
     *         最大长度，-1表示没有长度限制。
     * @param minValue
     *         最小值，空字符串表示没有最小值限制。
     * @param maxValue
     *         最大值，空字符串表示没有最大值限制。
     * @param pattern
     *         需要匹配的正则表达式样式，空字符串表示没有匹配限制。
     * @param optionsName
     *         关联的选项组名称。
     * @param prefix
     *         前缀。
     * @param suffix
     *         后缀。
     * @param options
     *         关联的选项列表。
     * @throws IllegalArgumentException
     *         如果输入框的名字是{@code null}或者只包含空白字符，如果宽度小于或者等于0，如果高度小于或者等于0，如果最大长度小于-1。
     */
    protected TextModel(
            LineInfo lineInfo,
            String name,
            boolean visible,
            TextModelType type,
            int size,
            int rowSize,
            boolean required,
            int maxLength,
            String minValue,
            String maxValue,
            String pattern,
            String optionsName,
            String prefix,
            String suffix,
            Collection<? extends OptionModel> options
    ) {
        super(lineInfo, name, visible);
        this.type = type;
        this.size = greaterThan(size, "size", 0);
        this.rowSize = greaterThan(rowSize, "rowSize", 0);
        this.required = required;
        this.maxLength = greaterThanOrEqual(maxLength, "maxLength", -1);
        this.minValue = trimToEmpty(minValue);
        this.maxValue = trimToEmpty(maxValue);
        this.pattern = trimToEmpty(pattern);
        this.prefix = prefix != null ? prefix : "";
        this.suffix = suffix != null ? suffix : "";
        this.optionsName = trimToEmpty(optionsName);
        this.options = options != null ? new ArrayList<>(options) : Collections.emptyList();
    }

    /**
     * 获取文本组件的显示类型。
     *
     * @return 文本组件的显示类型。
     */
    public final TextModelType getType() {
        return this.type;
    }

    /**
     * 获取文本组件的内容长度。
     *
     * @return 文本组件的内容长度。
     */
    public final int getSize() {
        return this.size;
    }

    /**
     * 获取文本组件的行数。
     * <p>1表示单行文本框，大于1则表示多行文本框。</p>
     *
     * @return 文本组件的行数。
     */
    public final int getRowSize() {
        return this.rowSize;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public final boolean isRequired() {
        return this.required;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public final int getMaxLength() {
        return this.maxLength;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public final String getMinValue() {
        return this.minValue;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public final String getMaxValue() {
        return this.maxValue;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public final String getPattern() {
        return this.pattern;
    }

    public final String getPrefix() {
        return this.prefix;
    }

    public final String getSuffix() {
        return this.suffix;
    }

    public final String getOptionsName() {
        return this.optionsName;
    }

    public final List<OptionModel> getOptions() {
        return Collections.unmodifiableList(this.options);
    }

    /**
     * 判断此文本框是否带有下拉列表。
     * <p>如果指定了选项列表，或者选项列表名字不为空，那么看作带有下拉列表。</p>
     *
     * @return 此文本框是否带有下拉列表。
     */
    public final boolean hasOptions() {
        return !this.optionsName.isEmpty() || !this.options.isEmpty();
    }
}
